package com.example.mrv.hrd;

import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.Vector;
import android.widget.AbsoluteLayout;

import static java.lang.Math.pow;
import static java.lang.StrictMath.abs;

public class GameListener implements View.OnTouchListener {
    GameActivity g;
    private int i;
    //起始位置在chessMap的编号
    private int xStart = basicGame.boundary;
    private int yStart = basicGame.boundary;
    //结束位置在chessMap的编号
    private int xEnd = 100;
    private int yEnd = 100;
    //起始位置在手机上的位置
    private float xStartLoc;
    private float yStartLoc;
    //滑动中的位置
    private float xChange;
    private float yChange;
    //手指当前坐标
    int xNow; int yNow;
    int xx = 0; int yy = 0;//x，y方向移动的块数量

    private boolean rState = false; private int rNum = 0;
    private boolean lState = false; private int lNum = 0;
    private boolean uState = false; private int uNum = 0;
    private boolean dState = false; private int dNum = 0;

    private Vector<Position> canBeThere = new Vector();

    public GameListener(GameActivity gameActivity) {
        g = gameActivity;

    }

    private class Position{
        int x;
        int y;
        int step;

        Position(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int eventAction = event.getAction();
        switch (eventAction) {
            case MotionEvent.ACTION_DOWN:
//                Log.d("Init","run down");
                setXYStart(event);
                break;
            case MotionEvent.ACTION_MOVE:
                setXYChange(event);
                AbsoluteLayout.LayoutParams layoutParamss = (AbsoluteLayout.LayoutParams) basicGame.chess[i].getLayoutParams();
                layoutParamss.x = (int)xChange;
                layoutParamss.y = (int)yChange;
                basicGame.chess[i].setLayoutParams(layoutParamss);
                break;
            case MotionEvent.ACTION_UP:
                Log.d("Init","run up: " + i);
                if(i>=0&&i<10) {//棋子
                    setXYEnd(event);
                    //更新位置
                    AbsoluteLayout.LayoutParams layoutParams = (AbsoluteLayout.LayoutParams) basicGame.chess[i].getLayoutParams();
                    layoutParams.x = (xEnd - 1) * basicGame.BlockWidth;
                    layoutParams.y = (yEnd - 1) * basicGame.BlockWidth;
                    basicGame.chess[i].setLayoutParams(layoutParams);
//                    Log.d("SetXYEnd", ""+xEnd+"###"+yEnd);
                    updateChessMap(i, basicGame.initState, xStart, yStart);
//                    updateChessMap(i, basicGame.initState, xNow, yNow);
                    updateChessMap(i, i, xEnd, yEnd);

                    basicGame.soundPool.play(basicGame.music[i], 1, 1, 0, 0, 1);
                }
                initStateAndNum();
                xx = 0; yy = 0;

                win();
                break;
        }
        return true;
    }

    private void win() {
//        Log.d("Win","run");
        for(int i=0;i<basicGame.xNum+2;i++)
            for(int j=0;j<basicGame.yNum+2;j++)
                Log.d("Init Activity", j+"####"+i+"####"+basicGame.chessMap[j][i]);
        if(basicGame.chessMap[5][2] == 1&&basicGame.chessMap[5][3] == 1){
            AlertDialog.Builder builder =  new AlertDialog.Builder(g, R.style.showWin);
            builder.setTitle("厉害，这都让你过了！");
            basicGame.soundPool.play(basicGame.music[11], 1, 1, 0, 0, 1);
            builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                   g.Over();
                   basicGame.isContinue = false;
                }
            });
            builder.show();
        }
    }

    private void updateChessMap(int j, int state,int x,int y) {
        for (int xx = 0; xx < basicGame.size[2 * j]; xx++) {
            for (int yy = 0; yy < basicGame.size[2 * j + 1]; yy++) {
                basicGame.chessMap[y + yy][x + xx] = state;
            }
        }
    }

    private void setXYChange(MotionEvent e) {
        initStateAndNum();
        //块当前位置 xNow yNow

        //手指移动距离
        float xDistance = e.getRawX() - xStartLoc - xx * basicGame.BlockWidth;
        float yDistance = e.getRawY() - yStartLoc - yy * basicGame.BlockWidth;
        setStateAndNum(xNow,yNow);
//        Log.d("SetXYChange", "xNow: "+xNow+"###YNow: "+yNow);

        xChange = (xNow - 1) * basicGame.BlockWidth;
        yChange = (yNow - 1) * basicGame.BlockWidth;
        if(xDistance > 0 && rState){
            if(xDistance >= basicGame.BlockWidth){
                if(xDistance >= basicGame.BlockWidth*rNum){
                    xDistance = basicGame.BlockWidth * (rNum - 1);
                }
                else xDistance = xDistance - basicGame.BlockWidth;
                updateChessMap(i, basicGame.initState, xNow, yNow);
                xNow += 1;
                xx += 1;
                updateChessMap(i, i, xNow, yNow);
//                Log.d("SetXYChange", "Right");
            }
            xChange = xDistance + (xNow - 1) * basicGame.BlockWidth;
//            Log.d("SetXYChange", "xDistance: "+xDistance);
        }
        else if(xDistance < 0 && lState){
            if(abs(xDistance) >= basicGame.BlockWidth) {
                if(abs(xDistance) >= basicGame.BlockWidth * lNum){
                    xDistance = -basicGame.BlockWidth * (lNum - 1);
                }
                else xDistance = xDistance + basicGame.BlockWidth;
                updateChessMap(i, basicGame.initState, xNow, yNow);
                xNow -= 1;
                xx -= 1;
                updateChessMap(i, i, xNow, yNow);
//                Log.d("SetXYChange", "Left");
            }
            xChange = xDistance + (xNow - 1) * basicGame.BlockWidth;
//            Log.d("SetXYChange", "xDistance: "+xDistance);
        }
        else if(yDistance > 0 && dState){
            if(yDistance >= basicGame.BlockWidth){
                if(yDistance >= basicGame.BlockWidth*dNum){
                    yDistance = basicGame.BlockWidth*(dNum-1);
                }
                else yDistance = yDistance - basicGame.BlockWidth;
                updateChessMap(i, basicGame.initState, xNow, yNow);
                yNow += 1;
                yy += 1;
                updateChessMap(i, i, xNow, yNow);
            }
            yChange = yDistance + (yNow - 1) * basicGame.BlockWidth;
//            Log.d("SetXYChange", "yDistance: "+yDistance);
        }
        else if(yDistance < 0 && uState){
            if(abs(yDistance) >= basicGame.BlockWidth){
                if(abs(yDistance) >= basicGame.BlockWidth * uNum){
                    yDistance = -basicGame.BlockWidth * (uNum - 1);
                }
                else yDistance = yDistance + basicGame.BlockWidth;
                updateChessMap(i, basicGame.initState, xNow, yNow);
                yNow -= 1;
                yy -= 1;
                updateChessMap(i, i, xNow, yNow);
            }
            yChange = yDistance + (yNow - 1) * basicGame.BlockWidth;
//            Log.d("SetXYChange", "yDistance: "+yDistance);
        }
//        for(int i=0;i<basicGame.xNum+2;i++)
//            for(int j=0;j<basicGame.yNum+2;j++)
//                Log.d("SetXYChange", j+"####"+i+"####"+basicGame.chessMap[j][i]);
//        Log.d("SetXYChange","####################");
    }

    private void initStateAndNum() {
        rState = false; rNum = 0;
        lState = false; lNum = 0;
        dState = false; dNum = 0;
        uState = false; uNum = 0;
    }

    private void setStateAndNum(int x, int y) {
        int index = basicGame.chessMap[y][x];
        if(index == 6||index == 7||index == 8||index == 9) {
            if (basicGame.chessMap[y][x + 1] == basicGame.initState) {//right
                rState = true;
                rNum += 1;
                if (basicGame.chessMap[y][x + 2] == basicGame.initState) {
                    rNum += 1;
                }
            }
            if (basicGame.chessMap[y][x - 1] == basicGame.initState) {//left
                lState = true;
                lNum += 1;
                if (basicGame.chessMap[y][x - 2] == basicGame.initState) {
                    lNum += 1;
                }
            }
            if (basicGame.chessMap[y + 1][x] == basicGame.initState) {//down
                dState = true;
                dNum += 1;
                if (basicGame.chessMap[y + 2][x] == basicGame.initState) {
                    dNum += 1;
                }
            }
            if (basicGame.chessMap[y - 1][x] == basicGame.initState) {//up
                uState = true;
                uNum += 1;
                if (basicGame.chessMap[y - 2][x] == basicGame.initState) {
                    uNum += 1;
                }
            }
        }
        if(index == 1){
            if(basicGame.chessMap[y][x+2] == basicGame.initState && basicGame.chessMap[y+1][x+2] == basicGame.initState){//right
                rState = true;
                rNum += 1;
                return;
            }
            else if(basicGame.chessMap[y][x-1] == basicGame.initState && basicGame.chessMap[y+1][x-1] == basicGame.initState){//left
                lState = true;
                lNum += 1;
                return;
            }
            else if(basicGame.chessMap[y+2][x] == basicGame.initState && basicGame.chessMap[y+2][x+1] == basicGame.initState) {//down
                dState = true;
                dNum += 1;
                return;
            }
            else if(basicGame.chessMap[y-1][x] == basicGame.initState && basicGame.chessMap[y-1][x+1] == basicGame.initState) {//up
                uState = true;
                uNum += 1;
                return;
            }
        }
        if(index==0||index==2||index==3||index==5){
            if(basicGame.chessMap[y][x+1] == basicGame.initState && basicGame.initState == basicGame.chessMap[y+1][x+1]){//right
                rState = true;
                rNum += 1;
            }
            if (basicGame.chessMap[y][x-1] == basicGame.initState && basicGame.initState == basicGame.chessMap[y+1][x-1]){//left
                lState = true;
                lNum += 1;
            }
            if(basicGame.chessMap[y+2][x] == basicGame.initState){//down
                dState = true;
                dNum += 1;
                if(basicGame.chessMap[y+3][x] == basicGame.initState){
                    dNum += 1;
                    return;
                }
            }
            if(basicGame.chessMap[y-1][x] == basicGame.initState) {//up
                uState = true;
                uNum += 1;
                if(basicGame.chessMap[y-2][x] == basicGame.initState) {
                    uNum += 1;
                    return;
                }
            }
        }
        if(i==4){
            if(basicGame.chessMap[y][x+2] == basicGame.initState) {//right
                rState = true;
                rNum += 1;
                if(basicGame.chessMap[y][x+3] == basicGame.initState) {
                    rNum += 1;
                    return;
                }
            }
            if(basicGame.chessMap[y][x-1] == basicGame.initState) {//left
                lState = true;
                lNum += 1;
                if(basicGame.chessMap[y][x-2] == basicGame.initState) {
                    lNum += 1;
                    return;
                }
            }
            if(basicGame.chessMap[y+1][x] == basicGame.initState &&basicGame.chessMap[y+1][x+1] == basicGame.initState) {//down
                dState = true;
                dNum += 1;
            }
            if(basicGame.chessMap[y-1][x] == basicGame.initState &&basicGame.chessMap[y-1][x+1] == basicGame.initState) {//down
                uState = true;
                uNum += 1;
            }
        }
        if(index > 9){
            Log.d("SetStateNum", "boundary or initState");
        }
    }

    private void setXYEnd(MotionEvent e) {
//        float xDistance = abs(e.getRawX() - (float)(xStart - 0.5) * basicGame.BlockWidth);
//        float yDistance = abs(e.getRawY() - (float)(yStart - 0.5) * basicGame.BlockWidth);
        updateChessMap(i,basicGame.initState,xNow,yNow);
        updateChessMap(i,i,xStart,yStart);
        float xDistance = abs(e.getRawX() - xStartLoc);
        float yDistance = abs(e.getRawY() - yStartLoc);
        if(xDistance < basicGame.BlockWidth / 2 && yDistance < basicGame.BlockWidth / 2){
//            Log.d("SetXYEnd",""+xDistance+"###"+yDistance+"###"+e.getRawX()+"###"+(float)(xStart - 0.5) * basicGame.BlockWidth+
//                    "###"+e.getRawY()+"###"+(float)(yStart - 0.5) * basicGame.BlockWidth);
//            Log.d("SetXYEnd",""+xDistance+"###"+yDistance+"###"+e.getRawX()+"###"+xStartLoc+
//                    "###"+e.getRawY()+"###"+yStartLoc);
            xEnd = xStart;
            yEnd = yStart;
            return;
        }
        int xTem = (int) e.getRawX() / basicGame.BlockWidth + 1;
        int yTem = (int) e.getRawY() / basicGame.BlockWidth + 1;
        int singleStep = 0;
        searchAllCanBe(xStart,yStart,2);
        int distance = 100;
        if(canBeThere.isEmpty()){
            xEnd = xStart;
            yEnd = yStart;
            return;
        }
//        Log.d("SetXYEnd","run"+xTem+"###"+yTem);
        for(Position p : canBeThere){
//            Log.d("SetXYEnd","run"+p.x+"###"+p.y);
            int tem = (int)pow((p.x - xTem), 2) + (int)pow(p.y - yTem, 2);
            if(tem < distance){
                distance = tem;
                xEnd = p.x;
                yEnd = p.y;
                singleStep = p.step;
            }
        }
        basicGame.step += singleStep;
        basicGame.showStep.setText(""+basicGame.step);
        canBeThere.removeAllElements();
//        Log.d("SetXYEnd",""+i+"###"+xEnd+"###"+yEnd);
    }

    private void searchAllCanBe(int x,int y,int time) {
        if(time == 0){
            return;
        }
        if(i == 6||i == 7||i == 8||i == 9) {
            if (basicGame.chessMap[y][x + 1] == basicGame.initState) {//right
                Position p = new Position(x + 1, y);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x + 1, y, time-1);
            }
            if (basicGame.chessMap[y][x - 1] == basicGame.initState) {//left
                Position p = new Position(x - 1, y);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x - 1, y, time-1);
            }
            if (basicGame.chessMap[y + 1][x] == basicGame.initState) {//down
                Position p = new Position(x, y + 1);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x, y + 1,time-1);
            }
            if (basicGame.chessMap[y - 1][x] == basicGame.initState) {//up
                Position p = new Position(x, y - 1);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x, y - 1,time-1);
            }
        }
        if(i == 1){
            if(basicGame.chessMap[y][x+2] == basicGame.initState && basicGame.chessMap[y+1][x+2] == basicGame.initState){//right
                Position p = new Position(x+1,y);
                p.step = 3 - time;
                canBeThere.add(p);
            }
            else if(basicGame.chessMap[y][x-1] == basicGame.initState && basicGame.chessMap[y+1][x-1] == basicGame.initState){//left
                Position p = new Position(x-1,y);
                p.step = 3 - time;
                canBeThere.add(p);
            }
            else if(basicGame.chessMap[y+2][x] == basicGame.initState && basicGame.chessMap[y+2][x+1] == basicGame.initState) {//down
                Position p = new Position(x,y+1);
                p.step = 3 - time;
                canBeThere.add(p);
            }
            else if(basicGame.chessMap[y-1][x] == basicGame.initState && basicGame.chessMap[y-1][x+1] == basicGame.initState) {//up
                Position p = new Position(x, y-1);
                canBeThere.add(p);
            }
        }
        if(i==0||i==2||i==3||i==5){
            if(basicGame.chessMap[y][x+1] == basicGame.initState && basicGame.initState == basicGame.chessMap[y+1][x+1]){//right
                Position p = new Position(x+1,y);
                p.step = 3 - time;
                canBeThere.add(p);
            }
            if (basicGame.chessMap[y][x-1] == basicGame.initState && basicGame.initState == basicGame.chessMap[y+1][x-1]){//left
                Position p = new Position(x-1,y);
                p.step = 3 - time;
                canBeThere.add(p);
            }
            if(basicGame.chessMap[y+2][x] == basicGame.initState){//down
                Position p = new Position(x,y+1);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x, y+1,time-1);
            }
            if(basicGame.chessMap[y-1][x] == basicGame.initState) {//up
                Position p = new Position(x,y-1);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x, y-1,time-1);
            }
        }
        if(i==4){
            if(basicGame.chessMap[y][x+2] == basicGame.initState) {//right
                Position p = new Position(x+1,y);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x+1, y,time-1);
            }
            if(basicGame.chessMap[y][x-1] == basicGame.initState) {//left
                Position p = new Position(x-1,y);
                p.step = 3 - time;
                canBeThere.add(p);
                searchAllCanBe(x-1, y,time-1);
            }
            if(basicGame.chessMap[y+1][x] == basicGame.initState &&basicGame.chessMap[y+1][x+1] == basicGame.initState) {//down
                Position p = new Position(x,y+1);
                p.step = 3 - time;
                canBeThere.add(p);
            }
            if(basicGame.chessMap[y-1][x] == basicGame.initState &&basicGame.chessMap[y-1][x+1] == basicGame.initState) {//up
                Position p = new Position(x,y-1);
                p.step = 3 - time;
                canBeThere.add(p);
            }
        }
    }

    private void setXYStart(MotionEvent e) {
        xStart = (int) e.getRawX() / basicGame.BlockWidth + 1;
        yStart = (int) e.getRawY() / basicGame.BlockWidth + 1;
        xStartLoc = e.getRawX();
        yStartLoc = e.getRawY();
        if(basicGame.chessMap[yStart][xStart] == basicGame.chessMap[yStart-1][xStart]){
            yStart -= 1;
        }
        if(basicGame.chessMap[yStart][xStart] == basicGame.chessMap[yStart][xStart-1]){
            xStart -= 1;
        }
        xNow = xStart;
        yNow = yStart;
        i = basicGame.chessMap[yStart][xStart];
//        Log.d("SetXYStart",""+i+"###"+xStart+"###"+yStart+"####"+e.getRawY()+"###"+e.getRawX()+"###"+basicGame.BlockWidth);
    }
}